package com.nexgo.payment.trans;

import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.nexgo.common.ByteUtils;
import com.nexgo.data.entity.RecvData;
import com.nexgo.data.entity.mapper.EntityDataMapper;
import com.nexgo.data.json.JsonRecData;
import com.nexgo.data.json.JsonSendData;
import com.nexgo.data.json.JsonTools;
import com.nexgo.data.json.bean.JsonBody;
import com.nexgo.lamp.LampOperate;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.oaf.apiv3.device.pinpad.WorkKeyTypeEnum;
import com.nexgo.oaf.apiv3.device.reader.CardInfoEntity;
import com.nexgo.oaf.apiv3.device.reader.CardReader;
import com.nexgo.oaf.apiv3.emv.CandidateAppInfoEntity;
import com.nexgo.oaf.apiv3.emv.EmvChannelTypeEnum;
import com.nexgo.oaf.apiv3.emv.EmvDataSourceEnum;
import com.nexgo.oaf.apiv3.emv.EmvHandler;
import com.nexgo.oaf.apiv3.emv.EmvOnlineResultEntity;
import com.nexgo.oaf.apiv3.emv.EmvProcessResultEntity;
import com.nexgo.oaf.apiv3.emv.EmvTransDataEntity;
import com.nexgo.oaf.apiv3.emv.EmvTransFlowEnum;
import com.nexgo.oaf.apiv3.emv.OnEmvProcessListener;
import com.nexgo.oaf.apiv3.emv.PromptEnum;
import com.nexgo.payment.App;
import com.nexgo.payment.BaseTransView;
import com.nexgo.payment.BuildConfig;
import com.nexgo.payment.R;
import com.nexgo.payment.action.ActionResult;
import com.nexgo.payment.action.ActionStep;
import com.nexgo.payment.aop.annotation.RunOnMainThread;
import com.nexgo.payment.api.ApiDeviceEngine;
import com.nexgo.payment.api.ApiLocationService;
import com.nexgo.payment.constrant.CardMode;
import com.nexgo.payment.constrant.OfflineState;
import com.nexgo.payment.constrant.PreferencesConstants;
import com.nexgo.payment.constrant.ResponseState;
import com.nexgo.payment.constrant.TransState;
import com.nexgo.payment.constrant.TransType;
import com.nexgo.payment.databases.DataSource;
import com.nexgo.payment.databases.Signature;
import com.nexgo.payment.databases.TransRecord;
import com.nexgo.payment.databases.mapper.TransRecordMapper;
import com.nexgo.payment.entity.CardInfo;
import com.nexgo.payment.entity.MessageData;
import com.nexgo.payment.entity.SignatureInfo;
import com.nexgo.payment.pack.DataBuilder;
import com.nexgo.payment.util.AidCapkUtils;
import com.nexgo.payment.util.ByteUtil;
import com.nexgo.payment.util.MessageHelper;
import com.nexgo.payment.util.RegexUtils;
import com.nexgo.payment.util.StringUtils;
import com.nexgo.payment.util.TransUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;

import cn.union.api.UnionApi;
import java8.util.Optional;

/**
 * 用卡交易流程处理，所有的用卡交易P层的父类，建议不要在这一层出现交易类型判断或是系统参数判断
 * <p>
 * Created by xiaox on 2017/2/22.
 */
public abstract class AbsTransPresenter extends AbsOnlinePresenter {
    private final Logger mLog = LoggerFactory.getLogger(AbsTransPresenter.class.getSimpleName());

    private final CardReader mSdkCardReader;
    private final PinPad mSdkPinPad;
    protected final EmvHandler mSdkEmvHandler;
    private int mPinRetryTimes;
    private RecvData mRecvData;
    private boolean mIsFirstTime = true;
    private EmvProcessResultEntity mEmvResult;
    private EmvTransDataEntity mEmvTransData;
    private int mEmvRetCode;
    private ApiLocationService mLocationService;

    protected AbsTransPresenter(@NonNull BaseTransView view, @NonNull DataSource repository) {
        super(view, repository);
        mSdkCardReader = ApiDeviceEngine.getInstance().getCardReader();
        mSdkPinPad = ApiDeviceEngine.getInstance().getPinPad();
        mSdkEmvHandler = ApiDeviceEngine.getDefaultEmvHandler();
//        mSdkEmvHandler.emvDebugLog(true);
        //测试用
        if (BuildConfig.LOG_DEBUG) {
            if (mSdkEmvHandler.getAidListNum() == 0) {
                mSdkEmvHandler.setAidParaList(AidCapkUtils.getProductionAidList());
            }
            if (mSdkEmvHandler.getCapkListNum() == 0) {
                mSdkEmvHandler.setCAPKList(AidCapkUtils.getProductionCapkList());
            }
        }
    }

    /**
     * 交易是否需要输入密码，如设置了撤销不用密码
     *
     * @return 是或否
     */
    private boolean isTransNeedPin() {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            if (transFlow.checkFreePinBySetting()) {
                mLog.debug("交易设置为需要输入密码");
                return TransUtils.isTransNeedPin(mTransData.getTransType(), mRepository);
            }
        }
        return true;
    }

    /**
     * 交易判断是否走qps的免密流程
     *
     * @param pan    卡号
     * @param amount 金额
     * @return 是或否
     */
    private boolean isQpsFreePin(String pan, String amount) {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            if (transFlow.checkQpsFreePin()) {
                mLog.debug("交易流程支持免密");
                return TransUtils.isQpsFreePin(pan, amount, mTransData.isCreditCard(), mRepository);
            }
        }
        return false;
    }

    /**
     * 交易判断是否走qps免签流程
     *
     * @param amount 金额
     * @return 是或否
     */
    private boolean isQpsFreeSignature(String amount) {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            if (transFlow.checkQpsFreeSignature()) {
                mLog.debug("交易流程支持免签");
                return TransUtils.isQpsFreeSignature(amount, mRepository);
            }
        }
        return false;
    }

    /**
     * 交易判断是否要发起电子签名步骤
     *
     * @return 是或否
     */
    private boolean isNeedElectronicSignature() {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            if (transFlow.checkNeedElectronicSignature()) {
                mLog.debug("交易流程支持电子签名");
                byte[] tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0x9f, 0x74}, EmvDataSourceEnum.FROM_KERNEL);
                return TransUtils.isNeedElectronicSignature(tlv != null, mRepository);
            }
        }
        return false;
    }

    /**
     * 交易判断是否要发起打印单步骤
     *
     * @return 是或否
     */
    private boolean isNeedReceipt() {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            boolean result = transFlow.checkNeedReceipt();
            if (result) {
                mLog.debug("交易流程支持打印签购单");
            }
            return result;
        } else {
            return true;
        }
    }

    /**
     * 获取emv流程配置
     *
     * @param channelType 接触还是非接
     * @return emv配置
     */
    protected abstract EmvTransDataEntity getEmvTransData(EmvChannelTypeEnum channelType);

    /**
     * 所有成功交易最后一步
     *
     * @param recvData  响应数据
     * @param emvResult
     */
    protected abstract void onTransSuccess(RecvData recvData, EmvProcessResultEntity emvResult);

    @Override
    @RunOnMainThread
    public void start() {
        if (mIsFirstTime) {
            mTransData = getTransData();
            onFirstAction();
            mIsFirstTime = false;
        }
    }

    @Override
    public void pause() {

    }

    @Override
    public void destroy() {
        cancelProcess();
    }

    @Override
    public void importActionResult(ActionResult actionResult) {
        Object data = actionResult.getData();
        ActionStep step = (ActionStep) actionResult.getAction().getActionStep();
        System.out.println("---------step:"+step);
        int ret = actionResult.getRet();
        mLog.debug("curr action step {} ret {}", step, actionResult.getRet());
        //特殊处理
        if (ret == ActionResult.ERR_CANCEL) {
            if (step.equals(ActionStep.CONFIRM_PAN)) {
                confirmPanNext(false);
                return;
            }
            if (step.equals(ActionStep.ONLINE)) {
                onlineNext(false, null);
                return;
            }
            if (step.equals(ActionStep.ELECTRONIC_SIGNATURE)) {
                electronicSignatureNext(null);
                return;
            }
            if (step.equals(ActionStep.INPUT_PIN)) {
                inputPinNext(false, null);
                return;
            }
            postMainThread(() -> mView.quitTrans());
            return;
        }
        if (ret == ActionResult.ERR_TIMEOUT) {
            if (step.equals(ActionStep.ONLINE)) {
                onlineNext(true, null);
                return;
            }
            if (step.equals(ActionStep.ELECTRONIC_SIGNATURE)) {
                electronicSignatureNext(null);
                return;
            }
        }
        if (ret == ActionResult.ERR_FAIL) {
            if (step.equals(ActionStep.ONLINE)) {
                onlineNext(true, null);
                return;
            }
            if (step.equals(ActionStep.ELECTRONIC_SIGNATURE)) {
                electronicSignatureNext(null);
                return;
            }
        }
        /*//lr 处理GPS获取失败的情况
        if(ret == ActionResult.ERR_GPS){
            mTransData.setTransType(TransType.GPSERR_NOTIFY);
            onTransOnlineProc();
            return;
        }*/
        //统一失败处理
        if (ret != ActionResult.SUCC) {
            String tip = (String) data;
            if (ret == ActionResult.ERR_TIMEOUT) {
                postMainThread(() -> mView.showError(StringUtils.firstNonEmpty(tip, getString(R.string.trans_timeout))));
            } else {
                if (!TextUtils.isEmpty(tip)) {
                    postMainThread(() -> mView.showError(tip));
                } else {
                    postMainThread(() -> mView.showTransFailed());
                }
            }
            return;
        }
        //成功处理
        if (ret == ActionResult.SUCC) {
            switch (step) {
                case INPUT_AMOUNT:
                    System.out.println("--------输入金额下一步----");
                    inputAmountNext(data);
                    break;
                case READ_CARD:
                    readCardNext(data);
                    break;
                case CONFIRM_SWITCH_EC:
                    confirmSwitchEcNext(data);
                    break;
                case SELECT_APP:
                    selectAppNext(data);
                    break;
                case CONFIRM_PAN:
                    confirmPanNext(data);
                    break;
                case INPUT_PIN:
                    System.out.println("--------输入密码下一步----");
                    inputPinNext(true, data);
                    break;
                case ONLINE:
                    System.out.println("--------开始联机交易----");
                    onlineNext(true, data);
                    break;
                case CONFIRM_CERT:
                    confirmCertNext(data);
                    break;
                case ELECTRONIC_SIGNATURE:
                    electronicSignatureNext(data);
                    break;
                case INPUT_PHONE:
                    inputSignaturePhoneNext(data);
                    break;
                case PRINT_RECEIPT:
                    printReceiptNext(data);
                    break;
                case EMV_PROMPT:
                    promptConfirmNext(data);
                    break;
                default:
                    break;
            }
        }
    }

    protected void promptConfirmNext(Object data) {
        mSdkEmvHandler.onSetPromptResponse((Boolean) data);
    }

    /**
     * 打印结束下一步动作
     *
     * @param data
     */
    protected void printReceiptNext(Object data) {
        onTransSuccess(mRecvData, mEmvResult);
    }

    /**
     * 电子签名完下一步动作
     *
     * @param data
     */
    protected void electronicSignatureNext(Object data) {
        if (data != null) {
            SignatureInfo info = (SignatureInfo) data;
            TransRecord lastTransRecord = mRepository.getLastSuccessfulTransRecord();
            //保存签名数据
            Signature signature = mRepository.getSignature(lastTransRecord.getTraceNum());
            if (signature == null) signature = new Signature();
            signature.setTraceNum(lastTransRecord.getTraceNum());
            //signature.setPhone(info.getPhone());
            signature.setSignatureData(Base64.encodeToString(info.getJbgData(), Base64.DEFAULT));
            signature.setIsOffline(OfflineState.APPROVE.equals(OfflineState.values()[lastTransRecord.getOfflineState()]));
            long result = mRepository.insertSignature(signature);
            mLog.debug("保存电子签名数据：{}", result);
            //判断是否要求输入手机号码
            if ("1".equals(mRepository.getParamValue(PreferencesConstants.IS_NEED_PHONE_NUMBER))) {
                postMainThread(() -> mView.showInputSignaturePhone());
                return;
            }
        }
        //判断是否需要打印签购单
        if (isNeedReceipt()) {
            postMainThread(() -> mView.showPrintReceipt());
        } else {
            onTransSuccess(mRecvData, mEmvResult);
        }
    }

    /**
     * 电子签名完成，输入电话号码后下一步
     *
     * @param data
     */
    protected void inputSignaturePhoneNext(Object data){
        if (data != null){
            String phone = (String) data;
            if (!TextUtils.isEmpty(phone)) {
                if (phone.length() != 11 || !RegexUtils.isMobileExact(phone)) {
                    postMainThread(() -> mView.showToast(getString(R.string.input_phone_number_err)));
                    return;
                }
                mLog.debug("输入电话号码：{}", phone);
                TransRecord lastTransRecord = mRepository.getLastSuccessfulTransRecord();
                Signature signature = mRepository.getSignature(lastTransRecord.getTraceNum());
                if (signature != null){
                    signature.setPhone(phone);
                    mRepository.updateSignature(signature);
                }
            }
        }
        postMainThread(() -> mView.showDismissInputPhone());
        //判断是否需要打印签购单
        if (isNeedReceipt()) {
            postMainThread(() -> mView.showPrintReceipt());
        } else {
            onTransSuccess(mRecvData, mEmvResult);
        }
    }

    /**
     * 确认证书下一步动作
     *
     * @param data
     */
    protected void confirmCertNext(Object data) {
        if (isICCTrans()) {
            mSdkEmvHandler.onSetCertVerifyResponse((Boolean) data);
        }
    }

    /**
     * 联机请求完下一步动作
     *
     * @param isConnected 是否已与后台交互
     * @param data
     */
    @Override
    protected void onlineNext(boolean isConnected, Object data) {
        //isConnected为false，说明无网络，此时未存包
        if (!isConnected) {
            postMainThread(() -> mView.showConnectFailed());
/*            if (isContactICCTrans()
                    && isEmvFullFlow()
                    && mEmvTransData.getB9C() == 0x00) {
                //全流程接触IC卡消费，在网络不通的时候下要请求走脱机
                mLog.debug("联机转脱机");
                mSdkEmvHandler.onSetOnlineProcResponse(SdkResult.Fail, null);
            } else {
                postMainThread(() -> mView.quitTrans());
            }*/
        } else {
            if (data == null) {
                //超时或接收失败等
                transFinish(TransState.ERR_NETWORK);
                return;
            }
            MessageData messageData = (MessageData) data;
            JsonRecData jsonRecData = messageData.getJsonRecData();
            JsonSendData jsonSendData = messageData.getJsonSendData();

            //第二层响应码判断
            if(jsonRecData.getREQ_BODY() == null) {
                postMainThread(() -> mView.showTransFailed());
                return;
            }
            if (!jsonRecData.getREQ_BODY().getResponseType().equals("N")) {
                if(jsonRecData.getREQ_BODY().getResponseType().equals("E")){
                    //原记录要置为失败记录
                    makeLastRecordAsFail();
                }
                String message=messageData.getJsonRecData().getREQ_BODY().getResponseMessage();
                String msg=messageData.getJsonRecData().getREQ_BODY().getResponseMsg();
                if (message != null) {
                    postMainThread(() -> mView.showError(message));
                } else if(msg != null){
                    postMainThread(() -> mView.showError(msg));
                }else {
                    postMainThread(() -> mView.showError(App.sContext.getString(R.string.trans_err)));
                }
                return;
            }
            //解密加密Decrypt
            String str = jsonRecData.getREQ_BODY().getDECRYPT();
            mLog.debug("加密Decrypt = {}",str);
            try {
                //xhj add
//                String str1 = UnionApi.getInstance().DecryptData(2, jsonSendData.getREQ_HEAD().getTranscode(),
//                        jsonSendData.getREQ_HEAD().getMcht_id(),jsonSendData.getREQ_HEAD().getTerm_trans_time(), str);
                //报文加密
                String str1 =ByteUtil.CalcByWKey(str,true);
                mLog.debug("解密Decrypt = {}",str1);
                jsonRecData.getREQ_BODY().setDECRYPT("{"+str1+"}");//解密出来的数据前后补{}
                System.out.println("");
                JsonBody jsonBody = JsonTools.fromJson( jsonRecData.getREQ_BODY().getDECRYPT(),JsonBody.class);

                if(jsonBody.get_$8583data() == null){
                    postMainThread(() -> mView.showTransFailed());
                    return;
                }
                byte[] recv8583Data = ByteUtils.commonString2Bcd(jsonBody.get_$8583data());
                mLog.debug("接收的8583 = {}", ByteUtils.byteArray2HexString(recv8583Data));
                //解8583包
                if(recv8583Data != null) {
                    final EntityDataMapper mapper = new EntityDataMapper();
                    RecvData recvData = mapper.rTransform(recv8583Data);

                    String keyData = new String();
                    if(jsonBody.getPin_key() != null){
                        keyData = keyData + jsonBody.getPin_key();
                    }
                    if(jsonBody.getPin_key_check() != null){
                        keyData = keyData + jsonBody.getPin_key_check();
                    }
                    if(jsonBody.getMac_key() != null){
                        keyData = keyData + jsonBody.getMac_key();
                    }
                    if(jsonBody.getMac_key_check() != null){
                        keyData = keyData + jsonBody.getMac_key_check();
                    }
                    if(jsonBody.getData_key() != null){
                        keyData = keyData + jsonBody.getData_key();
                    }
                    if(jsonBody.getData_key_check() != null){
                        keyData = keyData + jsonBody.getData_key_check();
                    }

                   /* recvData.setAdditionalRespData(jsonBody.getPin_key() + jsonBody.getPin_key_check()
                                    + jsonBody.getMac_key() + jsonBody.getMac_key_check()
//                                    + jsonBody.getData_key() + jsonBody.getData_key_check()
                    );*/
                    recvData.setAdditionalRespData(keyData);

                    messageData.setRecvData(recvData);
                }

            } catch (Exception e) {
                mLog.debug("处理接收数据失败");
                postMainThread(() -> mView.showTransFailed());
                e.printStackTrace();
                return;
            }

            mRecvData = messageData.getRecvData();
            String responseCode = mRecvData.getRespCode();
            String authCode = mRecvData.getAuthCode();
            String field55 = mRecvData.getEmvTlv();
            int keyIdx = Integer.parseInt(StringUtils.firstNonEmpty(mRepository.getParamValue(PreferencesConstants.MASTER_KEY_INDEX), "0"));
            ResponseState responseState = MessageHelper.checkResponse(messageData.getSendData(), messageData.getRecvData(), keyIdx);
            System.out.println("--------解包结束----responseState："+responseState);
            switch (responseState) {
                case ERR_MAC:
                    transFinish(TransState.ERR_CALCMAC);
                    break;
                case SUCCESS:
                case ERR_RESPONSE:
                    //A0特殊处理
                    if (TransUtils.isNeedReLogin(messageData.getRecvData().getRespCode())) {
                        mLog.debug("后台校验mac错");
                        mRepository.setParamValue(PreferencesConstants.IS_NEED_LOGIN, "1");
                        mRepository.syncParamValue();
                    }
                    boolean isSuccessfullyTrans = ResponseState.SUCCESS.equals(responseState);
                    //接触式全流程走二次授权
                    if (isContactICCTrans() && isEmvFullFlow()) {
                        EmvOnlineResultEntity onlineResult = new EmvOnlineResultEntity();
                        onlineResult.setRejCode(isSuccessfullyTrans ? "00" : responseCode);
                        onlineResult.setAuthCode(StringUtils.firstNonEmpty(authCode, "000000"));
                        if (!TextUtils.isEmpty(field55)) {
                            onlineResult.setRecvField55(ByteUtils.hexString2ByteArray(field55));
                        }
                        mLog.debug("二次授权");
                        mSdkEmvHandler.onSetOnlineProcResponse(SdkResult.Success, onlineResult);
                        return;
                    }
                    if (!isSuccessfullyTrans) {
                        mLog.debug("响应码错误 {}", responseCode);
                        if (TransType.SALE.equals(mTransData.getTransType()) && !isICCTrans()
                                && TransUtils.isPasswordIncorrect(responseCode) && mPinRetryTimes < 2) {
                            //磁条卡消费密码错，再输入两次
                            mLog.debug("密码错误");
                            mPinRetryTimes++;
                            //原记录要置为失败记录
                            makeLastRecordAsFail();
                            postMainThread(() -> mView.showInputPin(mTransData, true, 3 - mPinRetryTimes));
                            return;
                        }
                        transFinish(TransState.ERR_RESPONSE);
                        return;
                    }
                    transFinish(TransState.SUCCESS);
                    break;
                default:
                    transFinish(TransState.ERR_OTHER);
                    break;
            }
        }
    }
    /**
     * wzp add
     *
     * @param
     */
    public int updateWk( byte[] wkData) {
        byte[] tpkCKV = new byte[3];
        byte[] takCKV = new byte[3];
        byte[] tdkCKV = new byte[3];
        byte[] tpk = new byte[16];
        byte[] tak = new byte[8];
        byte[] tdk = new byte[16];
        byte []ckv;
        int sdkResult;

        if (wkData.length != 49 ) {
            mLog.error("工作密钥长度错误或校验值长度大于8 wkLen{}  wkData{}", wkData.length,wkData);
            return -4;
        }

        PinPad sdkPinPad = ApiDeviceEngine.getInstance().getPinPad();
        tpk = Arrays.copyOfRange(wkData, 0, 16);
        tpkCKV = Arrays.copyOfRange(wkData, 16, 3);
        tak = Arrays.copyOfRange(wkData, 19, 8);
        takCKV = Arrays.copyOfRange(wkData, 27, 3);
        tdk = Arrays.copyOfRange(wkData, 30, 16);
        tdkCKV = Arrays.copyOfRange(wkData, 46, 3);
        int mKeyIdx = Integer.parseInt(StringUtils.firstNonEmpty(mRepository.getParamValue(PreferencesConstants.MASTER_KEY_INDEX), "0"));
        try {
//            TPK
            sdkResult = sdkPinPad.writeWKey(mKeyIdx, WorkKeyTypeEnum.PINKEY, tpk, tpk.length);
            if (sdkResult != SdkResult.Success) {
                postMainThread(() -> mView.setWaitingIndicator(false,null,null));
                postMainThread(() -> mView.showError(App.sContext.getString(R.string.load_tpk_fail)));
                return sdkResult;
            }
            ckv = sdkPinPad.calcWKeyKCV(mKeyIdx, WorkKeyTypeEnum.PINKEY);
            mLog.debug("calc ckv {}", ByteUtils.byteArray2HexString(ckv));
            if (!ByteUtil.byteArrayCompare(tpkCKV, ckv,3)) {
                postMainThread(() -> mView.setWaitingIndicator(false,null,null));
                postMainThread(() -> mView.showError(App.sContext.getString(R.string.load_tdk_fail)));
                return SdkResult.Fail;
            }

//TAK
            sdkResult = sdkPinPad.writeWKey(mKeyIdx, WorkKeyTypeEnum.MACKEY, tak, tak.length);
            if (sdkResult != SdkResult.Success) {
                postMainThread(() -> mView.setWaitingIndicator(false,null,null));
                postMainThread(() -> mView.showError(App.sContext.getString(R.string.load_tpk_fail)));
                return sdkResult;
            }

            ckv = sdkPinPad.calcWKeyKCV(mKeyIdx, WorkKeyTypeEnum.MACKEY);
            mLog.debug("calc ckv {}", ByteUtils.byteArray2HexString(ckv));
            if (!ByteUtil.byteArrayCompare(takCKV, ckv,3)) {
                postMainThread(() -> mView.setWaitingIndicator(false,null,null));
                postMainThread(() -> mView.showError(App.sContext.getString(R.string.load_tdk_fail)));
                return SdkResult.Fail;
            }
//TDK
            sdkResult = sdkPinPad.writeWKey(mKeyIdx, WorkKeyTypeEnum.TDKEY, tdk, tdk.length);
            if (sdkResult != SdkResult.Success) {
                postMainThread(() -> mView.setWaitingIndicator(false,null,null));
                postMainThread(() -> mView.showError(App.sContext.getString(R.string.load_tpk_fail)));
                return sdkResult;
            }

            ckv = sdkPinPad.calcWKeyKCV(mKeyIdx, WorkKeyTypeEnum.TDKEY);
            mLog.debug("calc ckv {}", ByteUtils.byteArray2HexString(ckv));
            if (!ByteUtil.byteArrayCompare(tdkCKV, ckv,3)) {
                postMainThread(() -> mView.setWaitingIndicator(false,null,null));
                postMainThread(() -> mView.showError(App.sContext.getString(R.string.load_tdk_fail)));
                return SdkResult.Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SdkResult.Success;
    }

    /**
     * 交易结束总处理，包括了数据库的处理
     *
     * @param transState 交易状态
     */
    private void transFinish(TransState transState) {
        if (isICCTrans()) {
            if (!isEmvSimpleFlow()) {
                if (hasScript()) {
                    mLog.debug("获取脚本结果");
                    mTransData.setScriptTlv(getScriptTLV());
                }
                mLog.debug("更新55域emv数据");
                mTransData.setField55Tlv(getField55TLV());
            }
            if (TransState.SUCCESS.equals(transState)) {
                mLog.debug("获取emv交易结果相关tag信息");
                mTransData.setResultTlv(getTransResultTLV());
            }
            if (isEmvQpassFlow()) {
                if (TransState.SUCCESS.equals(transState)) {
                    LampOperate.getInstance().transSuccess();
                } else {
                    LampOperate.getInstance().transFailure();
                }
            }
        }
        switch (transState) {
            case SUCCESS:
                mTransData.setSuccess(true);
                mLog.debug("交易成功");
                //银联特色处理
                //判断是否免签，是-则设置免签标识为true
                if (isQpsFreeSignature(mTransData.getAmount())) {
                    mLog.debug("走了免签");
                    mTransData.setQpsFreeSignature(true);
                }
                //非接联机
                if (isEmvQpassFlow() && mEmvRetCode == SdkResult.Emv_Qpboc_Online) {
                    //判断是否走了cdcvm免密免签
                    if (mEmvTransData.isSupportCDCVM() && isCdcvm()) {
                        mLog.debug("走了CDCVM免密免签");
                        mTransData.setCdcvm(true);
                    }
                }
                //更新交易记录
                updateLastRecord(mRecvData);
                //判断是否需要电子签名
                boolean freeSignature = mTransData.isCdcvm() || mTransData.isQpsFreeSignature();
                if (isNeedElectronicSignature() && !freeSignature) {
                    postMainThread(() -> mView.showElectronicSignature(getSignatureCode()));
                } else if (isNeedReceipt()) {
                    postMainThread(() -> mView.showPrintReceipt());
                } else {
                    //返回交易数据
                    onTransSuccess(mRecvData, mEmvResult);
                }
                break;
            default:
                mTransData.setSuccess(false);
                mLog.debug("交易失败 {}", transState);
                //冲正原因码，更新是否需要冲正标志的时候是根据有无冲正码来判断的
                if (mTransData.getTransType().isReversal() && transState.isNeedReversal()) {
                    if (TransState.ERR_NETWORK.equals(transState)) {
                        mTransData.setReversalCode("98");
                    } else if (TransState.ERR_CALCMAC.equals(transState)) {
                        mTransData.setReversalCode("A0");
                    } else {
                        mTransData.setReversalCode("06");
                    }
                    mLog.debug("冲正码 {}", mTransData.getReversalCode());
                }
                updateLastRecord(mRecvData);
                //如果是响应码错，那提示响应码错，否则提示交易失败
                switch (transState) {
                    case ERR_RESPONSE:
                        showRespCodeError(mRecvData.getRespCode());
                        break;
                    case ERR_CALCMAC:
                        postMainThread(() -> mView.showError(getString(R.string.mac_check_err_trans_fail)));
                        break;
                    case ERR_OFFLINE_DECLINED:
                        postMainThread(() -> mView.showError(getString(R.string.offline_declined_trans_fail)));
                        break;
                    case ERR_OTHER:
                        postMainThread(() -> mView.showError(getString(R.string.message_type_no_match)));
                        break;
                    default:
                        postMainThread(() -> mView.showTransFailed());
                        break;
                }
                break;
        }
    }

    /**
     * 计算获取 电子签名特征码
     *
     * @return 返回特征码
     */
    private String getSignatureCode() {
        StringBuilder sb = new StringBuilder();
        TransRecord lastTransRecord = mRepository.getLastSuccessfulTransRecord();
        if (OfflineState.APPROVE.equals(OfflineState.values()[lastTransRecord.getOfflineState()])) {
            sb.append(lastTransRecord.getBatchNum());
            sb.append(lastTransRecord.getTraceNum());
            sb.append(StringUtils.leftPad("", 4, '0'));
        } else {
            sb.append(StringUtils.firstNonEmpty(lastTransRecord.getSettleDate(), StringUtils.leftPad("", 4, '0')));
            sb.append(StringUtils.firstNonEmpty(lastTransRecord.getRefNum(), StringUtils.leftPad("", 12, '0')));
        }
        byte[] code = ByteUtils.hexString2ByteArray(sb.toString());
        for (int i = 0; i < 4; i++) {
            code[i] ^= code[4 + i];
        }
        return ByteUtils.byteArray2HexString(code).substring(0, 8);
    }

    /**
     * 输入完密码后下一步动作
     *
     * @param isConfirm
     * @param data
     */
    protected void inputPinNext(boolean isConfirm, Object data) {
        postMainThread(() -> mView.setWaitingIndicator(true, getString(R.string.doing_something), getString(R.string.pls_wait)));
        if (isConfirm) {
            mTransData.setPin(Arrays.equals((byte[]) data, new byte[8]) ? null : (byte[]) data);
            mTransData.setEntryMode(TransUtils.getEntryMode(mTransData.getCardMode(), Optional.ofNullable(mEmvTransData).map(emvTransDataEntity -> emvTransDataEntity.getProcType()).orElse(null), mTransData.getPin() != null,mTransData.isFallback()));
            if (isICCTrans() && !isEmvSimpleFlow()) {
                mSdkEmvHandler.onSetPinInputResponse(true, data == null);
            } else {
                onTransOnlineProc();
            }
        } else {
            if (isICCTrans() && !isEmvSimpleFlow()) {
                mSdkEmvHandler.onSetPinInputResponse(false, false);
            } else {
                postMainThread(() -> mView.quitTrans());
            }
        }
    }

    /**
     * 确认完卡号后下一步动作
     *
     * @param data
     */
    protected void confirmPanNext(Object data) {
        boolean isConfirm = (boolean) data;
        switch (mTransData.getCardMode()) {
            case MANUAL:
            case SWIPE:
                if (isConfirm) {
                    if (isTransNeedPin()) {
                        onTransInputPin(true, 0);
                    } else {
                        onTransOnlineProc();
                    }
                } else {
                    postMainThread(() -> mView.quitTrans());
                }
                break;
            default:
                mSdkEmvHandler.onSetConfirmCardNoResponse((Boolean) data);
                break;
        }
    }

    /**
     * 选择完AID后下一步动作
     *
     * @param data
     */
    protected void selectAppNext(Object data) {
        if (isICCTrans()) {
            mSdkEmvHandler.onSetSelAppResponse((Integer) data);
        }
    }

    /**
     * 确认使用电子现金后下一步动作
     *
     * @param data
     */
    protected void confirmSwitchEcNext(Object data) {
        if (isICCTrans()) {
            mSdkEmvHandler.onSetConfirmEcSwitchResponse((Boolean) data);
        }
    }

    /**
     * 读卡完成后下一步动作
     *
     * @param data
     */
    protected void readCardNext(Object data) {
        CardInfo cardInfo = (CardInfo) data;
        mTransData.setCardMode(cardInfo.getCardMode());
        mTransData.setEntryMode(TransUtils.getEntryMode(mTransData.getCardMode(), null, mTransData.getPin() != null,mTransData.isFallback()));
        switch (mTransData.getCardMode()) {
            case MANUAL:
                mTransData.setPan(cardInfo.getPan());
                mTransData.setExpDate(cardInfo.getExpiredDate());
                confirmPanNext(true);
                break;
            case SWIPE:
                CardInfoEntity entity = new CardInfoEntity();
                entity.setCardNo(cardInfo.getPan());
                entity.setTk1(cardInfo.getTk1());
                entity.setTk2(cardInfo.getTk2());
                entity.setTk3(cardInfo.getTk3());
                entity.setExpiredDate(cardInfo.getExpiredDate());
                entity.setServiceCode(cardInfo.getServiceCode());
                onTransConfirmPan(entity);
                break;
            case INSERT:
            case TAP:
                EmvTransDataEntity emvTransData = null;
                if (CardMode.INSERT == mTransData.getCardMode()) {
                    emvTransData = getEmvTransData(EmvChannelTypeEnum.FROM_ICC);
                    //接触式就关了灯
                    LampOperate.getInstance().closeAll();
                } else {
                    emvTransData = getEmvTransData(EmvChannelTypeEnum.FROM_PICC);
                    LampOperate.getInstance().transOperateCard();
                }
                mEmvTransData = emvTransData;
                int result = mSdkEmvHandler.emvProcess(emvTransData, new EmvProcessListener());
                if (result == SdkResult.Success) {
                    mTransData.setEntryMode(TransUtils.getEntryMode(mTransData.getCardMode(), null, mTransData.getPin() != null,mTransData.isFallback()));
                    postMainThread(() -> mView.setWaitingIndicator(true, getString(R.string.card_reading), getString(R.string.do_not_remove_card)));
                } else {
                    postMainThread(() -> mView.showTransFailed());
                }
                break;
            default:
                confirmPanNext(true);
                break;
        }
    }

    /**
     * 输入完金额后下一步动作
     *
     * @param data
     */
    protected void inputAmountNext(Object data) {
        mTransData.setAmount(StringUtils.leftPad((String) data, 12, '0'));
        if (isICCTrans()) {
            mSdkEmvHandler.onSetRequestAmountResponse((String) data);
        } else {
            postMainThread(() -> mView.showReadCard(mTransData));
        }
    }

    @Override
    public void cancelProcess() {
        mSdkCardReader.stopSearch();
        mSdkPinPad.cancelInput();
    }

    @Override
    protected void onTransSuccess(RecvData recvData) {
        onTransSuccess(recvData, mEmvResult);
    }

    /**
     * EMV流程回调
     */
    public class EmvProcessListener implements OnEmvProcessListener {
        @Override
        public void onRequestAmount() {
            onEmvRequestAmount();
        }

        @Override
        public void onSelApp(List<String> appNameList, List<CandidateAppInfoEntity> appInfoList, boolean isFirstSelect) {
            onEmvSelApp(appNameList, appInfoList, isFirstSelect);
        }

        @Override
        public void onConfirmEcSwitch() {
            onEmvConfirmEcSwitch();
        }

        @Override
        public void onConfirmCardNo(CardInfoEntity cardInfo) {
            onTransConfirmPan(cardInfo);
        }

        @Override
        public void onCardHolderInputPin(boolean isOnlinePin, int leftTimes) {
            onTransInputPin(isOnlinePin, leftTimes);
        }

        @Override
        public void onCertVerify(String certName, String certInfo) {
            onEmvCerVerify(certName, certInfo);
        }

        @Override
        public void onOnlineProc() {
            onTransOnlineProc();
        }

        @Override
        public void onReadCardAgain() {
            onEmvReadCardAgain();
        }

        @Override
        public void onAfterFinalSelectedApp() {
            onEmvAfterFinalSelectedApp();
        }

        @Override
        public void onFinish(int retCode, EmvProcessResultEntity entity) {
            onEmvFinish(retCode, entity);
        }

        @Override
        public void onPrompt(PromptEnum promptEnum) {
            onEmvPrompt(promptEnum);
        }
    }

    protected void onEmvPrompt(PromptEnum promptEnum) {
        postMainThread(() -> mView.showEmvPrompt(promptEnum));
    }


    /**
     * EMV流程结束
     *
     * @param retCode
     * @param entity
     */
    protected void onEmvFinish(int retCode, EmvProcessResultEntity entity) {
        mLog.debug("EMV流程结束");
        postMainThread(() -> mView.setWaitingIndicator(false, null, null));
        mEmvResult = entity;
        mEmvRetCode = retCode;
        mLog.debug("EMV retCode {}", retCode);
        switch (retCode) {
            case SdkResult.Emv_Success_Arpc_Fail:
                mTransData.setArpcErr(true);
            case SdkResult.Success:
                //简化流程
                if (isEmvSimpleFlow()) {
                    onSimpleTransFlowSuccess();
                } else {
                    transFinish(TransState.SUCCESS);
                }
                break;
            case SdkResult.Emv_Qpboc_Offline:
            case SdkResult.Emv_Offline_Accept:
            case SdkResult.Emv_Ec_Accept:
                mTransData.setOfflineState(OfflineState.APPROVE);
                DataBuilder.getInstance(mTransData, mRepository).build();
                transFinish(TransState.SUCCESS);
                break;
            case SdkResult.Emv_Qpboc_Online:
                onTransOnlineProc();
                break;
            case SdkResult.Emv_Arpc_Fail:
            case SdkResult.Emv_Script_Fail:
            case SdkResult.Emv_Declined:
                //后台响应错误也走了二次授权，这里再判断一次是不是响应码错
                if (!MessageHelper.isSuccessful(mRecvData.getRespCode())) {
                    transFinish(TransState.ERR_RESPONSE);
                } else {
                    transFinish(TransState.ERR_ONLINE_DECLINED);
                }
                break;
            case SdkResult.Emv_Cancel:
                postMainThread(() -> mView.quitTrans());
                break;
            case SdkResult.Emv_Offline_Declined:
                mTransData.setOfflineState(OfflineState.DECLINED);
                DataBuilder.getInstance(mTransData, mRepository).build();
                transFinish(TransState.ERR_OFFLINE_DECLINED);
                break;
            case SdkResult.Emv_Card_Block:
                postMainThread(() -> mView.showError(getString(R.string.card_block)));
                break;
            case SdkResult.Emv_Candidatelist_Empty:
                postMainThread(() -> mView.showError(getString(R.string.candidate_list_empty)));
                break;
            case SdkResult.Emv_App_Block:
                postMainThread(() -> mView.showError(getString(R.string.app_block)));
                break;
            case SdkResult.Emv_App_Ineffect:
                postMainThread(() -> mView.showError(getString(R.string.app_ineffect)));
                break;
            case SdkResult.Emv_App_Expired:
                postMainThread(() -> mView.showError(getString(R.string.app_expired)));
                break;
            case SdkResult.Emv_FallBack:
                mTransData.setFallback(true);
                mEmvTransData = null;
                postMainThread(() -> mView.showReadCard(mTransData));
                break;
            case SdkResult.Emv_Other_Interface:
                postMainThread(() -> mView.showError(getString(R.string.please_try_other_communication)));
                break;
            default:
                postMainThread(() -> mView.showTransFailed());
                break;
        }
    }

    /**
     * 应用选择完后用于设置 tlv 参数等
     */
    private void onEmvAfterFinalSelectedApp() {
        mSdkEmvHandler.onSetAfterFinalSelectedAppResponse(true);
    }

    /**
     * 请求再次挥卡
     */
    protected void onEmvReadCardAgain() {
        //paypass,paywave用，国内不会走到这个回调
        mLog.debug("请求再次挥卡");
        // FIXME: 2017/10/18 国外的话这里要加重新寻卡
        mSdkEmvHandler.onSetReadCardAgainResponse(true);
    }

    /**
     * 请求证书确认
     *
     * @param certName
     * @param certInfo
     */
    protected void onEmvCerVerify(String certName, String certInfo) {
        mLog.debug("请求证书确认");
        postMainThread(() -> mView.showCertVerify(certName, certInfo));
    }

    /**
     * 请求确认是否使用电子现金
     */
    protected void onEmvConfirmEcSwitch() {
        mLog.debug("请求是否使用电子现金");
        postMainThread(() -> mView.showConfirmEcSwitch());
    }

    /**
     * 请求AID列表选择
     *
     * @param appNameList
     * @param appInfoList
     * @param isFirstSelect
     */
    protected void onEmvSelApp(List<String> appNameList, List<CandidateAppInfoEntity> appInfoList, boolean isFirstSelect) {
        mLog.debug("请求选择aid列表");
        for (String aid : appNameList) {
            mLog.debug("{}", aid);
        }
        postMainThread(() -> mView.showSelApp(appNameList));
    }

    /**
     * EMV请求输入金额
     */
    protected void onEmvRequestAmount() {
        mLog.debug("请求输入金额");
        postMainThread(() -> mView.showInputAmount(mTransData));
    }

    /**
     * 请求联机
     */
    protected void onTransOnlineProc() {
        mLog.debug("请求联机");
        postMainThread(() -> mView.setWaitingIndicator(false, null, null));
        if (isICCTrans()) {
            if (!isEmvSimpleFlow()) {
                mTransData.setField55Tlv(getField55TLV());
                mTransData.setReversalTlv(getReversalTLV());
            }
            mTransData.setResultTlv(getTransResultTLV());
        }
        postMainThread(() -> mView.showOnlineProc(mTransData, null));
    }

    /**
     * 请求输入pin
     *
     * @param isOnlinePin
     * @param leftTimes
     */
    protected void onTransInputPin(boolean isOnlinePin, int leftTimes) {
        mLog.debug("请求输入密码");
        mLog.debug("isOnlinePin：{}，leftTimes：{}", isOnlinePin, leftTimes);
        postMainThread(() -> mView.setWaitingIndicator(false, null, null));
        //磁条卡
        if (!isICCTrans()) {
            if (isTransNeedPin()) {
                mLog.debug("交易设置为要求输入密码");
                postMainThread(() -> mView.showInputPin(mTransData, true, 0));
            } else {
                onTransOnlineProc();
            }
        } else {
            if (isOnlinePin) {
                switch (mEmvTransData.getProcType()) {
                    case FULL:
                        postMainThread(() -> mView.showInputPin(mTransData, true, 0));
                        break;
                    case QPASS:
                        LampOperate.getInstance().transConnecting();
                        if (mTransData.isForcePin()) {
                            mLog.debug("非接强制输pin");
                            postMainThread(() -> mView.showInputPin(mTransData, true, 0));
                        } else {
                            if (isTransNeedPin()) {
                                //国外借记卡，不要求输密
                                if (isForeignCard() && isNoPwdRequired() && !isCreditCard()) {
                                    mLog.debug("国外借记卡，不要求输密");
                                    mSdkEmvHandler.onSetPinInputResponse(true, true);
                                } else {
                                    if (isQpsFreePin(mTransData.getPan(), mTransData.getAmount())) {
                                        mLog.debug("非接免密");
                                        mTransData.setQpsFreePin(true);
                                        mSdkEmvHandler.onSetPinInputResponse(true, true);
                                    } else {
                                        postMainThread(() -> mView.showInputPin(mTransData, true, 0));
                                    }
                                }
                            } else {
                                mSdkEmvHandler.onSetPinInputResponse(true, true);
                            }
                        }
                        break;
                    case SIMPLE:
                        if (isTransNeedPin()) {
                            postMainThread(() -> mView.showInputPin(mTransData, true, 0));
                        } else {
                            onTransOnlineProc();
                        }
                        break;
                    default:
                        break;
                }
            } else {
                postMainThread(() -> mView.showInputPin(mTransData, false, leftTimes));
            }
        }
    }

    /**
     * 请求卡号确认
     *
     * @param cardInfo
     */
    protected void onTransConfirmPan(CardInfoEntity cardInfo) {
        mLog.debug("请求确认卡号");
        mTransData.setPan(cardInfo.getCardNo());
        mTransData.setTk1(cardInfo.getTk1());
        mTransData.setTk2(cardInfo.getTk2());
        mTransData.setTk3(cardInfo.getTk3());
        mTransData.setExpDate(cardInfo.getExpiredDate());
        mTransData.setServiceCode(cardInfo.getServiceCode());
        mTransData.setCsn(Optional.ofNullable(cardInfo.getCsn()).orElse("000"));
        if (isEmvQpassFlow()) {
            LampOperate.getInstance().transRemoveCard();
            mTransData.setCreditCard(isCreditCard());
        }
        //都要求确认卡号，卡号界面出不出现由确认卡号p层决定
        postMainThread(() -> mView.setWaitingIndicator(false, null, null));
        postMainThread(() -> mView.showCardNoConfirm(mTransData));
    }

    /**
     * 接触式简化流程读卡完成，如子类希望只读卡号而不去联机，可以重写此方法
     */
    protected void onSimpleTransFlowSuccess() {
        if (isTransNeedPin()) {
            onTransInputPin(true, 0);
        } else {
            onTransOnlineProc();
        }
    }

    /**
     * 获取交易结束所需要的emv数据，如打印单emv栏内容等
     *
     * @return
     */
    private String getTransResultTLV() {
        final String[] TAGS = {"95", "9b", "9f36", "9f26", "91", "9f10", "df31", "9f79", "9f27", "84", "9f06", "50", "9f12", "9f33", "9f37",
                "9f34", "82", "9f5d", "9a", "9c", "9f02", "5f2a", "9f1a", "9f03", "9f35", "9f1e", "9f09", "9f41", "8a", "5f34", "9f74", "5a", "57", "9f63"};
        return mSdkEmvHandler.getTlvByTags(TAGS);
    }

    /**
     * 获取脚本通知所需要的emv数据
     *
     * @return
     */
    private String getScriptTLV() {
        final String[] TAGS = {"9f33", "95", "9f37", "9f1e", "9f10", "9f26", "9f36", "82", "df31", "9f1a", "9a"};
        return mSdkEmvHandler.getTlvByTags(TAGS);
    }

    /**
     * 获取55域emv数据
     *
     * @return
     */
    private String getField55TLV() {
        if (mTransData.getOfflineState() == OfflineState.APPROVE) {
            return getOfflineTLV();
        } else {
            return getARQCTLV();
        }
    }

    /**
     * 获取脱机交易的55域emv数据
     *
     * @return
     */
    private String getOfflineTLV() {
        final String[] TAGS = {"9f26", "9f27", "9f10", "9f37", "9f36", "95", "9a", "9c", "9f02", "5f2a", "82", "9f1a", "9f03",
                "9f33", "9f1e", "84", "9f09", "9f41", "9f34", "9f35", "9f63", "9f74", "8a", "9f24"};
        return mSdkEmvHandler.getTlvByTags(TAGS);
    }

    /**
     * 获取联机交易的55域emv数据
     *
     * @return
     */
    private String getARQCTLV() {
        final String[] TAGS = {"9f26", "9f27", "9f10", "9f37", "9f36", "95", "9a", "9c", "9f02", "5f2a", "82", "9f1a", "9f03",
                "9f33", "9f34", "9f35", "9f1e", "9f09", "84", "9f41", "9f63", "9f24"};
        return mSdkEmvHandler.getTlvByTags(TAGS);
    }

    /**
     * 获取冲正上送时需要的55域emv数据
     *
     * @return
     */
    private String getReversalTLV() {
        final String[] TAGS = {"95", "9f1e", "9f10", "9f36", "df31"};
        return mSdkEmvHandler.getTlvByTags(TAGS);
    }

    /**
     * 更新最后一条交易记录
     *
     * @param recvData
     */
    private void updateLastRecord(RecvData recvData) {
        if (mTransData.getTransType().isSaveRecord() || mTransData.getTransType().isReversal()) {
            TransRecord lastTransRecord = mRepository.getLastTransRecord();
            if (lastTransRecord != null) {
                mLog.debug("更新最后一笔交易记录，流水号{}", lastTransRecord.getTraceNum());
                mRepository.updateTransRecord(new TransRecordMapper().transform(mTransData, recvData, lastTransRecord));
                //更新原交易撤销标识，处理码前两位为20表示退货，包括撤销
                if (TransType.values()[lastTransRecord.getTransType()].getProcCode().startsWith("20")
                        && mTransData.isSuccess()) {
                    //判断源凭证号是否存在
                    String orgTraceNum = lastTransRecord.getOrgTraceNum();
                    if (!TextUtils.isEmpty(orgTraceNum)) {
                        TransRecord orgTransRecord = mRepository.queryTransRecord(orgTraceNum);
                        if (orgTransRecord != null && orgTransRecord.getIsSuccess()) {
                            //设置为已撤销
                            orgTransRecord.setIsVoid(true);
                            mRepository.updateTransRecord(orgTransRecord);
                        }
                    }
                }
            }
        }
    }

    /**
     * 让最后一条交易记录置为失败
     */
    private void makeLastRecordAsFail() {
        if (mTransData.getTransType().isSaveRecord() || mTransData.getTransType().isReversal()) {
            TransRecord lastTransRecord = mRepository.getLastTransRecord();
            if (lastTransRecord != null) {
                lastTransRecord.setIsSuccess(false);
                lastTransRecord.setIsNeedReversal(false);
                mRepository.updateTransRecord(lastTransRecord);
            }
        }
    }

    /**
     * 获取用卡方式，22域
     *
     * @return
     */
    protected String getEntryMode() {
        String field = "0";
        switch (mTransData.getCardMode()) {
            case MANUAL:
                field += "01";
                break;
            case SWIPE:
                Log.d("wzp", "getEntryMode: isFallback" + mTransData.isFallback());
//                wzp add
                if(mTransData.isFallback()){
                    field += "80";
                }else{
                    field += "02";
                }
                break;
            case INSERT:
                field += "05";
                break;
            case TAP:
                if (isEmvFullFlow()) {
                    field += "98";
                } else {
                    field += "07";
                }
                break;
            case SCAN:
                field += "03";
                break;
            default:
                field += "01";
                break;
        }
        if (mTransData.getPin() != null) {
            field += "1";
        } else {
            field += "2";
        }
        return field;
    }
    /**
     * 31域
     *
     * @return 默认PNCN00000
     */
    protected String getPayMark() {
        String field = "P";
        switch (mTransData.getCardMode()) {
            case TAP:
                if(!mTransData.isQpsFreePin()){
                    field += "1";
                }else{
                    field += "0";
                }
                break;
            default: //刷卡直接返回
                field += "0CN00000";
                return field;
        }
        //
        field += "C";
        byte[] tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0x9f, 0x10}, EmvDataSourceEnum.FROM_KERNEL);
        //9f10 :07 01 01 03 a0 00 00 01 0d 07 01 00 00 00 00 00 80 b0 b9 e4 24 cd applepay
        mLog.debug("RF pay flag = {}",ByteUtils.byteArray2HexString(tlv));
        if (tlv!= null) {
            final String str = ByteUtils.byteArray2HexString(tlv);
            if(tlv[9] == (byte)0xA1){ //hce
                field +="9";
            }else {
                if("0701".equals(str.substring(18,22))){
                    mLog.debug("11111111");
                    if((tlv[16] == (byte)0x80) && ((byte)(tlv[17] & 0xf0) == (byte)0xB0)){ //apple[ay 07010103a00000010d0701000000000080b0b9e424cd
                        field += "1";
                    }else {
                        field += "0";
                    }
                }else if("0702".equals(str.substring(18,22))){
                    if ("803043".equals(str.substring(32,38))){ //sumsung pay
                        field +="2";
                    }else if("803041".equals(str.substring(32,38))){ //huawei pay 07020103a00000010f070200000000008030410011792268
                        field += "3";
                    }else if("803042".equals(str.substring(32,38))){ //xiaomi pay
                        field += "5";
                    }else{
                        field +="0";
                    }
                }
            }
        } else {
            field += "0";
        }
        field += "00000";
        return field;
    }
    /*private String getValue(String tlv, String tag) {
        if (TextUtils.isEmpty(tlv) || TextUtils.isEmpty(tag)) return null;
        List<String> values = TlvUtils.decodingTLV(tlv, tag);
        return values.size() > 0 ? values.get(0) : null;
    }*/
    /**
     * 是否是国外的卡片，判断条件为货币/国家代码不为156
     *
     * @return
     */
    private boolean isForeignCard() {
        byte[] tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0x9f, 0x51}, EmvDataSourceEnum.FROM_KERNEL);
        if (tlv != null) {
            if (Arrays.equals(tlv, new byte[]{0x01, 0x56})) {
                return false;
            }
        }
        tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0xdf, 0x71}, EmvDataSourceEnum.FROM_KERNEL);
        if (tlv != null) {
            if (Arrays.equals(tlv, new byte[]{0x01, 0x56})) {
                return false;
            }
        }
        return true;
    }

    /**
     * 是否卡片要求不需要输入密码
     *
     * @return
     */
    private boolean isNoPwdRequired() {
        byte[] tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0x9f, 0x6c}, EmvDataSourceEnum.FROM_KERNEL);
        return tlv != null && (tlv[0] & 0x80) == 0x80;
    }

    /**
     * 是否有脚本结果
     *
     * @return
     */
    private boolean hasScript() {
        byte[] tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0xdf, 0x31}, EmvDataSourceEnum.FROM_KERNEL);
        return tlv != null && tlv.length > 0;
    }

    /**
     * 是否为IC卡交易
     *
     * @return
     */
    private boolean isICCTrans() {
        return ((mTransData.getCardMode() == CardMode.INSERT) || (mTransData.getCardMode() == CardMode.TAP));
    }

    /**
     * 是否为接触式IC卡交易
     *
     * @return
     */
    private boolean isContactICCTrans() {
        return mTransData.getCardMode() == CardMode.INSERT;
    }

    /**
     * 是否简化流程
     *
     * @return
     */
    private boolean isEmvSimpleFlow() {
        return mEmvTransData != null && EmvTransFlowEnum.SIMPLE.equals(mEmvTransData.getProcType());
    }

    /**
     * 是否全流程
     *
     * @return
     */
    private boolean isEmvFullFlow() {
        return mEmvTransData != null && EmvTransFlowEnum.FULL.equals(mEmvTransData.getProcType());
    }

    /**
     * 是否qpass流程
     *
     * @return
     */
    private boolean isEmvQpassFlow() {
        return mEmvTransData != null && EmvTransFlowEnum.QPASS.equals(mEmvTransData.getProcType());
    }

    /**
     * 是否不要求pin且cdcvm已执行
     *
     * @return
     */
    private boolean isCdcvm() {
        byte[] tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0x9f, 0x6c}, EmvDataSourceEnum.FROM_KERNEL);
        return tlv != null && ((tlv[0] & 0x80) == 0 && (tlv[1] & 0x80) == 0x80);
    }

    /**
     * 是否为信用卡
     *
     * @return
     */
    private boolean isCreditCard() {
        byte[] tlv = mSdkEmvHandler.getTlv(new byte[]{(byte) 0x9f, 0x06}, EmvDataSourceEnum.FROM_KERNEL);
        return tlv != null && tlv.length >= 8
                && (Arrays.equals(Arrays.copyOf(tlv, 8), ByteUtils.hexString2ByteArray("A000000333010102"))
                || Arrays.equals(Arrays.copyOf(tlv, 8), ByteUtils.hexString2ByteArray("A000000333010103")));
    }

    private String getString(@StringRes int resId) {
        return App.sContext.getString(resId);
    }

}
